package org.javaforever.cookieshop.serviceimpl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.javaforever.cookieshop.dao.GoodsDao;
import org.javaforever.cookieshop.domain.GoodsBean;
import org.javaforever.cookieshop.domain.PageBean;
import org.javaforever.cookieshop.domain.RecommendBean;
import org.javaforever.cookieshop.domain.TypeBean;
import org.javaforever.cookieshop.service.GoodsService;
import org.javaforever.cookieshop.service.TypeService;
import org.javaforever.cookieshop.utils.ImageUtil;
import org.javaforever.cookieshop.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;

@Service
public class GoodsServiceImpl implements GoodsService{
	@Autowired
	protected GoodsDao dao;
	
	@Autowired
	protected TypeService typeService;

	@PersistenceContext
	protected EntityManager entityManager;

	@Override
	public void activateAllGoodses(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.activateGoods(id);
        }
	}

	@Override
	public Boolean activateGoods(Long id) throws Exception{
        dao.activateGoods(id);
        return true;
	}

	@Override
	@Transactional
	public Boolean addGoods(GoodsBean goods) throws Exception{
        dao.saveAndFlush(goods);
        return true;
	}

	@Override
	public void cloneAllGoodses(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            cloneGoods(id);
        }
	}

	@Override
	public Boolean cloneGoods(Long id) throws Exception{
        GoodsBean goods = dao.findGoodsFullInfoById(id);
        
        String name = goods.getName();
        String shortName = name;
        if (name.contains("_") && StringUtil.isInteger(name.substring(name.lastIndexOf('_')+1,name.length()))) {
            shortName = name.substring(0,name.lastIndexOf('_'));
        }
        List<GoodsBean> names = dao.searchGoodsIndexedNamesByShortName(shortName);
        int indexNum = 1;
        for (GoodsBean goods0:names) {
            String _name = goods0.getName();
            if (_name.contains("_") && StringUtil.isInteger(_name.substring(_name.lastIndexOf('_')+1,_name.length()))) {
                int index = Integer.valueOf(_name.substring(_name.lastIndexOf('_')+1,_name.length()));
                if (index >= indexNum) {
                    indexNum = index + 1;
                }
            }
        }
        String indexName = shortName + "_" + indexNum;
        GoodsBean goods1 = goods.clone();
        goods1.setId(null);
        goods1.setName(indexName);
        addGoods(goods1);
        return true;
	}

	@Override
	public Integer countActiveGoodsRecords() throws Exception{
        return dao.countActiveGoodsRecords();
	}

	@Override
	public Integer countSearchGoodsesByFieldsRecords(GoodsBean goods) throws Exception{
        String jpql = "select count(*) as countNum from GoodsBean g where 1=1 ";
        if (goods.getName() != null) {
            jpql += " and g.name like CONCAT('%', '"+goods.getName()+"','%')";
        }
        if (goods.getActive() != null) {
            jpql += " and g.active = "+goods.getActive();
        }
        if (goods.getPrice() != null) {
            jpql += " and abs(g.price - "+goods.getPrice()+") < 0.0001";
        }
        if (goods.getIntro() != null) {
            jpql += " and g.intro like CONCAT('%', '"+goods.getIntro()+"','%')";
        }
        if (goods.getStock() != null) {
            jpql += " and g.stock = "+goods.getStock();
        }
        if (goods.getType() != null) {
            jpql += " and g.type = "+goods.getType();
        }
        if (goods.getIsScroll() != null) {
            jpql += " and g.isScroll = "+goods.getIsScroll();
        }
        if (goods.getIsHot() != null) {
            jpql += " and g.isHot = "+goods.getIsHot();
        }
        if (goods.getIsNew() != null) {
            jpql += " and g.isNew = "+goods.getIsNew();
        }
        Query query = entityManager.createQuery(jpql);
        Long count = (Long) query.getSingleResult();
        return count.intValue();
	}

	@Override
	public void deleteAllGoodses(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.deleteGoods(id);
        }
	}

	@Override
	public Boolean deleteGoods(Long id) throws Exception{
        dao.deleteGoods(id);
        return true;
	}

	@Override
	public GoodsBean findGoodsById(Long id) throws Exception{
		GoodsBean goods = dao.findGoodsById(id);
		TypeBean tempType = typeService.findTypeById(goods.getType());
		if (tempType != null) goods.setTypeName(tempType.getName());
		goods.setCoverStr(ImageUtil.encodeToBase64(goods.getCover()));
		goods.setImage1Str(ImageUtil.encodeToBase64(goods.getImage1()));
		goods.setImage2Str(ImageUtil.encodeToBase64(goods.getImage2()));
		return goods;
	}

	@Override
	public GoodsBean findGoodsByName(String name) throws Exception{
        return dao.findGoodsByName(name);
	}

	@Override
	public List<GoodsBean> listActiveGoodses() throws Exception{
        return dao.listActiveGoodses();
	}

	@Override
	public List<GoodsBean> listAllGoodses() throws Exception{
        return dao.listAllGoodses();
	}

	@Override
	public List<GoodsBean> searchGoodsesByFields(GoodsBean goods) throws Exception{
        String jpql = "from GoodsBean g where 1=1 ";
        if (goods.getName() != null) {
            jpql += " and g.name like CONCAT('%', '"+goods.getName()+"','%')";
        }
        if (goods.getActive() != null) {
            jpql += " and g.active = "+goods.getActive();
        }
        if (goods.getPrice() != null) {
            jpql += " and abs(g.price - "+goods.getPrice()+") < 0.0001";
        }
        if (goods.getIntro() != null) {
            jpql += " and g.intro like CONCAT('%', '"+goods.getIntro()+"','%')";
        }
        if (goods.getStock() != null) {
            jpql += " and g.stock = "+goods.getStock();
        }
        if (goods.getType() != null) {
            jpql += " and g.type = "+goods.getType();
        }
        if (goods.getIsScroll() != null) {
            jpql += " and g.isScroll = "+goods.getIsScroll();
        }
        if (goods.getIsHot() != null) {
            jpql += " and g.isHot = "+goods.getIsHot();
        }
        if (goods.getIsNew() != null) {
            jpql += " and g.isNew = "+goods.getIsNew();
        }
        Query query = entityManager.createQuery(jpql);
        List<GoodsBean> results = query.getResultList();
        return results;
	}

	@Override
	public List<GoodsBean> searchGoodsesByFieldsByPage(GoodsBean goods,Integer pagesize,Integer pagenum) throws Exception{
        Integer start = (pagenum-1)*pagesize;
        Integer limit = pagesize;
        String jpql = "from GoodsBean g where 1=1 ";
        if (goods.getName() != null) {
            jpql += " and g.name like CONCAT('%', '"+goods.getName()+"','%')";
        }
        if (goods.getActive() != null) {
            jpql += " and g.active = "+goods.getActive();
        }
        if (goods.getPrice() != null) {
            jpql += " and abs(g.price - "+goods.getPrice()+") < 0.0001";
        }
        if (goods.getIntro() != null) {
            jpql += " and g.intro like CONCAT('%', '"+goods.getIntro()+"','%')";
        }
        if (goods.getStock() != null) {
            jpql += " and g.stock = "+goods.getStock();
        }
        if (goods.getType() != null) {
            jpql += " and g.type = "+goods.getType();
        }
        if (goods.getIsScroll() != null) {
            jpql += " and g.isScroll = "+goods.getIsScroll();
        }
        if (goods.getIsHot() != null) {
            jpql += " and g.isHot = "+goods.getIsHot();
        }
        if (goods.getIsNew() != null) {
            jpql += " and g.isNew = "+goods.getIsNew();
        }
        Query query = entityManager.createQuery(jpql);
        query.setFirstResult(start); // 设置起始位置
        query.setMaxResults(limit); // 设置返回结果数量
        List<GoodsBean> results = query.getResultList();
        return results;
	}

	public void setDao(GoodsDao dao){
		this.dao = dao;
	}

	@Override
	public void softDeleteAllGoodses(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.softDeleteGoods(id);
        }
	}

	@Override
	public boolean softDeleteGoods(Long id) throws Exception{
        dao.softDeleteGoods(id);
        return true;
	}

	@Override
	public Boolean toggleGoods(Long id) throws Exception{
        dao.toggleGoods(id);
        return true;
	}

	@Override
	public Boolean toggleOneGoods(Long id) throws Exception{
        GoodsBean goods = dao.findGoodsById(id);
        if (goods.getActive()==false) {
            dao.toggleGoods(id);
        }
        else {
            Integer count = dao.countActiveGoodsRecords();
            if (count > 1){
                dao.toggleGoods(id);
            }
        }
        return true;
	}

	@Override
	@Transactional
	public Boolean updateGoods(GoodsBean goods) throws Exception{
        entityManager.merge(goods);
        return true;
	}
	
	@Override
    public List<GoodsBean> selectGoodsByTypeID(Long typeId, int pagenum, int pagesize)
    {
        List<GoodsBean> list=null;
        try {
            Integer start = (pagenum-1)*pagesize;
            Integer limit = pagesize;
            if(typeId==0)
            {
                String jpql ="from GoodsBean g where g.active = true";
                Query query = entityManager.createQuery(jpql);
                query.setFirstResult(start); // 设置起始位置
                query.setMaxResults(limit); // 设置返回结果数量
                List<GoodsBean> results = query.getResultList();
                List<GoodsBean> retVals = new ArrayList<>();
                for (GoodsBean g: results) {
                	g.setCoverStr(ImageUtil.encodeToBase64(g.getCover()));
                	g.setImage1Str(ImageUtil.encodeToBase64(g.getImage1()));
                	g.setImage2Str(ImageUtil.encodeToBase64(g.getImage2())); 
                	if (!"".equals(g.getCoverStr())) retVals.add(g);
                }
                return retVals;
            }
            else
            {
                String jpql ="from GoodsBean g where g.type = ?1 and g.active = true";
                Query query = entityManager.createQuery(jpql);
                query.setParameter(1, typeId);
                List<GoodsBean> results = query.getResultList();
                List<GoodsBean> retVals = new ArrayList<>();
                for (GoodsBean g: results) {
                	g.setCoverStr(ImageUtil.encodeToBase64(g.getCover()));
                	g.setImage1Str(ImageUtil.encodeToBase64(g.getImage1()));
                	g.setImage2Str(ImageUtil.encodeToBase64(g.getImage2())); 
                	if (!"".equals(g.getCoverStr())) retVals.add(g);
                }
                Integer end = start + limit < retVals.size() ? start + limit : retVals.size(); 
                return retVals.subList(start, end);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

	@Override
    public PageBean selectPageByTypeID(Long typeId,int pagenum)
    {
    	PageBean p=new PageBean();
        p.setPageNumber(pagenum);
        int totalCount=0;
        try {
            if(typeId==0)
            {
                String jpql ="select count(*) as countNum from GoodsBean g";
                Query query = entityManager.createQuery(jpql);
                Long count = (Long) query.getSingleResult();
                totalCount = count.intValue();
            }
            else
            {
                String jpql ="select count(*) from GoodsBean g where g.type = ?1";
                Query query = entityManager.createQuery(jpql);
                query.setParameter(1, typeId);
                Long count = (Long) query.getSingleResult();
                totalCount = count.intValue();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        p.SetPageSizeAndTotalCount(8,totalCount);

        List list=null;
        try {
            list= selectGoodsByTypeID(typeId,pagenum,8);
        } catch (Exception e) {
            e.printStackTrace();
        }

        p.setList(list);
        return p;
    }
	
	@Override
    public List<GoodsBean> getGoodsList(int recommendType) throws SQLException {
        String sql="select g.id,g.name,g.cover,g.price,t.name typename from cs_recommends r,cs_goodses g,cs_types t where g.type=? and r.goods=g.id and g.type=t.id";
        Query query = entityManager.createNativeQuery(sql);
        query.setParameter(1, recommendType);
        List<Object[]> rawResults = query.getResultList();
        List<GoodsBean> results = new ArrayList<>();
        for (Object[] row : rawResults) {
        	GoodsBean goods = new GoodsBean(); 
        	goods.setId((Long) row[0]);
        	goods.setName((String) row[1]);
        	goods.setCover((byte []) row[2]);
        	goods.setPrice((Double) row[3]);
        	goods.setTypeName((String) row[4]);
        	goods.setCoverStr(ImageUtil.encodeToBase64(goods.getCover()));
        	goods.setImage1Str(ImageUtil.encodeToBase64(goods.getImage1()));
        	goods.setImage2Str(ImageUtil.encodeToBase64(goods.getImage2()));
            results.add(goods);
        }
        return results;
    }
	
	@Override
    public List<GoodsBean> getScrollGood()throws SQLException{
        String sql="select g.id,g.name,g.cover,g.price  from cs_recommends r, cs_goodses g where r.goods=g.id";
        Query query = entityManager.createNativeQuery(sql);
        List<Object[]> rawResults = query.getResultList();
        List<GoodsBean> results = new ArrayList<>();
        for (Object[] row : rawResults) {
        	GoodsBean goods = new GoodsBean(); 
        	goods.setId((Long) row[0]);
        	goods.setName((String) row[1]);
        	goods.setCover((byte []) row[2]);
        	goods.setCoverStr(ImageUtil.encodeToBase64(goods.getCover()));
        	goods.setPrice((Double) row[3]);
            if (!goods.getCoverStr().equals("")) results.add(goods);
        }
        return results;
    }
	
	@Override
	public PageBean getGoodsRecommendPage(Long type,int pageNumber) {
		PageBean p = new PageBean();
        p.setPageNumber(pageNumber);
        int totalCount = 0;
        try {
            totalCount = getRecommendCountOfGoodsByTypeID(type);
	        p.SetPageSizeAndTotalCount(8, totalCount);
	        List list=null;
            list = selectGoodsbyRecommend(type, pageNumber, 8);
            for(GoodsBean g : (List<GoodsBean>)list) {
                g.setIsScroll(isScroll(g));
                g.setIsHot(isHot(g));
                g.setIsNew(isNew(g));
            }
	        p.setList(list);
	        return p;
	    } catch (Exception e) {
	        e.printStackTrace();
	        return null;
	    }
	}

	@Override
	public List<GoodsBean> selectGoodsbyRecommend(Long type,int pageNumber,int pageSize) throws Exception {
	   Integer start = (pageNumber-1)*pageSize;
	   Integer limit = pageSize;
	   if(type==0) {
	       //当不添加推荐类型限制的时候
		   String jpql = "from GoodsBean g where g.active = true order by g.id";
		   Query query = entityManager.createQuery(jpql);
		   List<GoodsBean> rawResults = (List<GoodsBean>)query.getResultList();
		   List<GoodsBean> results = new ArrayList<>();
	       for (GoodsBean goods : rawResults) {
	        	goods.setCoverStr(ImageUtil.encodeToBase64(goods.getCover()));
	        	goods.setImage1Str(ImageUtil.encodeToBase64(goods.getImage1()));
	        	goods.setImage2Str(ImageUtil.encodeToBase64(goods.getImage2()));
	        	TypeBean tempType = typeService.findTypeById(goods.getType());
	        	if (tempType != null) goods.setTypeName(tempType.getName());
	            if (!goods.getCoverStr().equals("")) results.add(goods);
	        }
	        Integer end = start + limit < results.size() ? start + limit : results.size();
	        return results.subList(start, end);
	   }else {
		   String jpql = "from GoodsBean g,RecommendBean r,TypeBean t where g.id=r.goods and g.type=t.id and r.type=?1 order by g.id";
		   Query query = entityManager.createQuery(jpql);
		   query.setParameter(1, type);
		   List<Object[]> rawResults = query.getResultList();
		   List<GoodsBean> results = new ArrayList<>();
		   for (Object[] row : rawResults) {
	        	GoodsBean goods = (GoodsBean) row[0];
	        	goods.setCoverStr(ImageUtil.encodeToBase64(goods.getCover()));
	        	goods.setImage1Str(ImageUtil.encodeToBase64(goods.getImage1()));
	        	goods.setImage2Str(ImageUtil.encodeToBase64(goods.getImage2()));
	            if (!goods.getCoverStr().equals("")) results.add(goods);
	        }
	        Integer end = start + limit < results.size() ? start + limit : results.size();
	        return results.subList(start, end);
	   }
    } 
   
   @Override
   public int getRecommendCountOfGoodsByTypeID(Long type) throws SQLException {
 	   if(type==0) {
 		   //当不添加推荐类型限制的时候
 		   String jpql = "select count(*) as countNum from GoodsBean g,TypeBean t where g.active= true and g.cover != null and g.type = t.id order by g.id";
 		   Query query = entityManager.createQuery(jpql);
 		   Long count = (Long) query.getSingleResult();
 		   return count.intValue();
 	   }else {
 		   String jpql = "select count(*) as countNum from GoodsBean g,RecommendBean r,TypeBean t where g.active= true and g.cover != null and g.id=r.goods and g.type=t.id and r.type=?1 order by g.id";
 		   Query query = entityManager.createQuery(jpql);
 		   query.setParameter(1, type);
 		   Long count = (Long) query.getSingleResult();
 		   return count.intValue();
 	   }
    }
    
    public boolean isScroll(GoodsBean g) throws SQLException {
        return isRecommend(g, 1);
    }
    public boolean isHot(GoodsBean g) throws SQLException {
        return isRecommend(g, 2);
    }
    public boolean isNew(GoodsBean g) throws SQLException {
        return isRecommend(g, 3);
    }
    
    private boolean isRecommend(GoodsBean g,int type) throws SQLException {
        String jpql = "from RecommendBean r where r.type=?1 and r.goods=?2";
        Query query = entityManager.createQuery(jpql);
        query.setParameter(1, type);
        query.setParameter(2, g.getId());
        List<RecommendBean> recommends = (List<RecommendBean>)query.getResultList();
        if(recommends == null || recommends.size() == 0) {
            return false;
        }else {
            return true;
        }
    }
    
    @Override
    public PageBean getSearchGoodsPage(String keyword, int pageNumber) {
        try {
	    	PageBean p = new PageBean();
	        p.setPageNumber(pageNumber);
	        int totalCount = totalCount = dao.getSearchCount(keyword);
	        p.SetPageSizeAndTotalCount(8, totalCount);
	        List list=null;
	        list = selectSearchGoods(keyword,pageNumber,8);
	        p.setList(list);
	        return p;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public List<GoodsBean> selectSearchGoods(String keyword, int pageNumber, int pageSize) throws SQLException{
    	Integer start = (pageNumber-1)*pageSize;
    	Integer limit = pageSize;
    	String jpql = "from GoodsBean g where g.name like CONCAT('%',?1, '%')";
        Query query = entityManager.createQuery(jpql);
        query.setParameter(1, keyword);
		   List<GoodsBean> rawResults = query.getResultList();
		   List<GoodsBean> results = new ArrayList<>();
		   for (GoodsBean g : rawResults) {
				g.setCoverStr(ImageUtil.encodeToBase64(g.getCover()));
				g.setImage1Str(ImageUtil.encodeToBase64(g.getImage1()));
				g.setImage2Str(ImageUtil.encodeToBase64(g.getImage2()));
				if (!g.getCoverStr().equals("")) results.add(g);
		   }
			Integer end = start + limit < results.size() ? start + limit : results.size();
			return results.subList(start, end);
    }
    
    @Override
    public void addRecommend(Long id,int type) throws Exception{
    	dao.addRecommend(id, type);
    }
    
    @Override
    public void removeRecommend(Long id,int type) throws Exception{
    	dao.removeRecommend(id, type);
    }
 }
